--- title: The peak pattern puzzle keywords: fastai sidebar: home_sidebar summary: "Matching peak patterns " description: "Matching peak patterns " nb_path: "notebooks/50_peak-pattern-puzzle.ipynb" ---
{% raw %}
{% endraw %}

In the previous steps we have computed the hotmax spectra and within each spectrum detected peaks above the Poisson noise level. All this preliminary work was needed to arrive at the central problem of MA-XRF analysis: solving the peak pattern puzzle. For each individual hotmax spectrum I would like to explain the presence of all peaks above the Poisson noise level.

{% raw %}
from maxrf4u import HotmaxAtlas 

hma = HotmaxAtlas('RP-T-1898-A-3689.datastack')

hma.plot_spectra()
2022-12-02T13:09:14.164519 image/svg+xml Matplotlib v3.5.3, https://matplotlib.org/
{% endraw %}

It is important to note that not all peaks are due to the presence of chemical elements in the scanned object. Some peaks are generated by the instrument itself. These instrument peaks can show up in all spectra. The peak that is seen near zero energy is somehow a result of the instrument detector. Other peaks above 18 keV are due emission and scattering of the rhodium anode present in the x-ray tube.

Now, let's take a look at the emission patterns for a selection of elements of interest eoi in this context. If you want to include other elements in your plot you can uncomment the respective elements.

{% raw %}
from maxrf4u import all_elements 

# elements of interest
elements = [elem for elem in all_elements if not '#' in elem]

print(f'all_elements={all_elements}\n')
print(elements)
all_elements=['#H', '#He', '#Li', '#Be', '#B', '#C', 'N', 'O', 'F', 'Ne', 'Na', 'Mg', 'Al', 'Si', 'P', 'S', 'Cl', '#Ar', 'K', 'Ca', '#Sc', 'Ti', 'V', 'Cr', 'Mn', 'Fe', 'Co', 'Ni', 'Cu', 'Zn', '#Ga', '#Ge', 'As', '#Se', 'Br', '#Kr', '#Rb', 'Sr', '#Y', '#Zr', '#Nb', '#Mo', '#Tc', '#Ru', 'Rh', '#Pd', 'Ag', 'Cd', '#In', 'Sn', '#Sb', '#Te', 'I', '#Xe', '#Cs', 'Ba', '#La', '#Hf', '#Ta', '#W', '#Re', '#Os', '#Ir', '#Pt', '#Au', 'Hg', '#Tl', 'Pb', '#Bi', '#Po', '#At', '#Rn', '#Fr', '#Ra', '#Ac', '#Rf', '#Db', '#Sg', '#Bh', '#Hs', '#Mt', '#Ds', '#Rg', '#Cn', '#Nh', '#Fl', '#Mc', '#Lv', '#Ts', '#Og']

['N', 'O', 'F', 'Ne', 'Na', 'Mg', 'Al', 'Si', 'P', 'S', 'Cl', 'K', 'Ca', 'Ti', 'V', 'Cr', 'Mn', 'Fe', 'Co', 'Ni', 'Cu', 'Zn', 'As', 'Br', 'Sr', 'Rh', 'Ag', 'Cd', 'Sn', 'I', 'Ba', 'Hg', 'Pb']
{% endraw %}

We can plot the corresponding peak patterns with the functions get_patterns() and plot_patterns(). In order to include the instrument peak pattern, set the option instrument=True and datastack_file name.

{% raw %}
from maxrf4u import get_patterns, plot_patterns
{% endraw %} {% raw %}
element_patterns = get_patterns(elements)
plot_patterns(element_patterns, instrument=True, datastack_file='RP-T-1898-A-3689.datastack');
{% endraw %}

Now we can start to 'explain away' all peaks. It is highly instructive to walk through all hotmax spectra and see which element patterns explain the peak patterns that we observe. To do so, import the plot_puzzle() and plot_ptrn() functions. In the following we silently ignore the instrument peaks $\times$ on the extreme ends of the spectrum.

{% raw %}
from maxrf4u import plot_puzzle, plot_ptrn 
{% endraw %} {% raw %}
hma = HotmaxAtlas('RP-T-1898-A-3689.datastack')
{% endraw %} {% raw %}
n = 0
ax0, ax1 = plot_puzzle(hma, n) 

# patterns 
plot_ptrn('Ca', -1, ax1);
{% endraw %} {% raw %}
n = 1
ax0, ax1 = plot_puzzle(hma, n) 

# patterns 
plot_ptrn('O', -1, ax1);
plot_ptrn('Ca', -1, ax1);
{% endraw %} {% raw %}
n = 2
ax0, ax1 = plot_puzzle(hma, n)


# patterns 
plot_ptrn('Pb', -1, ax1);
{% endraw %} {% raw %}
n = 3
ax0, ax1 = plot_puzzle(hma, n)

# patterns 
plot_ptrn('Cl', -1, ax1);
plot_ptrn('Ca', -1, ax1);
plot_ptrn('Fe', -2, ax1);
{% endraw %} {% raw %}
n = 4
ax0, ax1 = plot_puzzle(hma, n)

# patterns 
plot_ptrn('Fe', -3, ax1)
plot_ptrn('Ca', -1, ax1)
plot_ptrn('O', -1, ax1)
plot_ptrn('S', -1, ax1)
plot_ptrn('K', -2, ax1);
{% endraw %} {% raw %}
n = 5
ax0, ax1 = plot_puzzle(hma, n)

# patterns 
plot_ptrn('Ca', -1, ax1);
{% endraw %} {% raw %}
n = 6
ax0, ax1 = plot_puzzle(hma, n)

# patterns 
plot_ptrn('Ca', -1, ax1);
{% endraw %} {% raw %}
n = 7
ax0, ax1 = plot_puzzle(hma, n)

# patterns 
plot_ptrn('Fe', -1, ax1);
plot_ptrn('Ti', -2, ax1);
plot_ptrn('Ca', -3, ax1);
{% endraw %} {% raw %}
n = 8
ax0, ax1 = plot_puzzle(hma, n)

# patterns 
plot_ptrn('Fe', -3, ax1);
plot_ptrn('Ba', -1, ax1);
plot_ptrn('Ca', -2, ax1);
{% endraw %} {% raw %}
n = 9
ax0, ax1 = plot_puzzle(hma, n)

# patterns 
plot_ptrn('Mn', -1, ax1);
plot_ptrn('Ca', -2, ax1);
plot_ptrn('Fe', -3, ax1);
{% endraw %} {% raw %}
n = 10
ax0, ax1 = plot_puzzle(hma, n)

# patterns 
plot_ptrn('Fe', -1, ax1);
plot_ptrn('Ca', -2, ax1);
{% endraw %}

The tiny peak [6] in hotmax spectrum #10 is clearly the escape peak for Fe located at 6.40 keV minus 1.74 keV.

{% raw %}
n = 11
ax0, ax1 = plot_puzzle(hma, n)

# patterns 
plot_ptrn('Fe', -1, ax1);
plot_ptrn('Ca', -2, ax1);
{% endraw %} {% raw %}
n = 12
ax0, ax1 = plot_puzzle(hma, n)

# patterns 
plot_ptrn('Cu', -1, ax1);
plot_ptrn('Zn', -2, ax1);
plot_ptrn('Ca', -3, ax1);
{% endraw %} {% raw %}
n = 13
ax0, ax1 = plot_puzzle(hma, n)

# patterns 
plot_ptrn('Cu', -1, ax1);
plot_ptrn('Zn', -2, ax1);
plot_ptrn('Ca', -3, ax1);
{% endraw %} {% raw %}
n = 14
ax0, ax1 = plot_puzzle(hma, n)

# patterns 
plot_ptrn('Cu', -1, ax1);
plot_ptrn('Zn', -2, ax1);
plot_ptrn('Ca', -3, ax1);
{% endraw %} {% raw %}
n = 15
ax0, ax1 = plot_puzzle(hma, n)

# patterns 
plot_ptrn('Pb', -1, ax1);
{% endraw %} {% raw %}
n = 16
ax0, ax1 = plot_puzzle(hma, n)

# patterns 
plot_ptrn('Pb', -1, ax1);
{% endraw %} {% raw %}
n = 17
ax0, ax1 = plot_puzzle(hma, n)

# patterns 
plot_ptrn('Ca', -1, ax1);
{% endraw %} {% raw %}
n = 18
ax0, ax1 = plot_puzzle(hma, n)

# patterns 
plot_ptrn('Pb', -1, ax1);
{% endraw %} {% raw %}
n = 19
ax0, ax1 = plot_puzzle(hma, n)

# patterns 
plot_ptrn('Ca', -1, ax1);
{% endraw %} {% raw %}
n = 20
ax0, ax1 = plot_puzzle(hma, n)

# patterns 
plot_ptrn('Pb', -1, ax1);
{% endraw %}

Ok, that is it. Let's try to summarize what we have learned...

Summary

{% raw %}
from maxrf4u import plot_patterns, get_patterns, DataStack 
from maxrf4u.peakmaps import _add_hotlines_ticklabels

ds = DataStack('RP-T-1898-A-3689.datastack')

x_keVs = ds.read('maxrf_energies') 
y_max = ds.read('maxrf_maxspectrum')
y_sum = ds.read('maxrf_sumspectrum') 
hotmax_spectra = ds.read('hotmax_spectra')

ptrn_list = get_patterns(['S', 'Ca', 'K', 'Cl', 'Fe', 'Mn', 'Cu', 'Zn', 'Pb', 'Ti', 'Ba'])

fig, [ax, ax1] = plt.subplots(nrows=2, sharex=True, figsize=[9, 5])

plot_patterns(ptrn_list, ax=ax)
_add_hotlines_ticklabels('RP-T-1898-A-3689.datastack', ax, clip_vline=False) 

#plot_cube_slices('RP-T-1898-A-3689.datastack', ax=ax1); 

ax1.plot(x_keVs, y_max, color='r', label='max spectrum') 
ax1.fill_between(x_keVs, y_max, color='r', alpha=0.3)

for y_hot in hotmax_spectra: 
    ax1.plot(x_keVs, y_hot, color=[0.2, 0.1, 0.8], linewidth=0.5) 
#ax1.plot(x_keVs, y_sum, color=[0.3, 1, 0.3], label='sum spectrum')
_add_hotlines_ticklabels('RP-T-1898-A-3689.datastack', ax1) 

ax1.set_xlim([-1, 23])
ax1.set_ylim([-5, 100])
ax1.legend();

ax.set_title('Peak pattern summary')
plt.tight_layout()
{% endraw %}

Altogether the spectral data indicates that 11 chemical elements are present in the Susanna drawing: sulfur (S), chlorine (Cl), potassium (K), calcium (Ca), barium (Ba), titanium (Ti), manganese (Mn), iron (Fe), copper (Cu), zinc (Zn) and lead (Pb).

In the next section we will look into the spatial distribution of these elements...

Functions

{% raw %}

get_patterns[source]

get_patterns(elements, tube_keV=30, eoi=None)

Returns sorted pattern dict list for `elements` list, according to alpha peak energy.
{% endraw %} {% raw %}

colorize[source]

colorize(elem, eoi=None)

Pick fixed color from nice color map for elements of interest.
{% endraw %} {% raw %}

plot_ptrn[source]

plot_ptrn(elem, y, ax, eoi=None, escape=True)

Low level plot element pattern at level `y` in axes `ax`.
{% endraw %} {% raw %}

plot_patterns[source]

plot_patterns(ptrn_list, instrument=False, datastack_file=None, ax=None, eoi=None, escape=True)

Plot overview of instrument and element patterns `ptrn_list` in axes `ax`

Returns: `ax`
{% endraw %} {% raw %}

plot_puzzle[source]

plot_puzzle(hma, n)

{% endraw %} {% raw %}

get_instrument_pattern[source]

get_instrument_pattern(datastack_file)

Generate instrument peak pattern.

Pattern dictionary contains strongest Rhodium anode emission peaks,
their corresponding Compton shifted peaks, and a sensor peak

Returns: instrument_pattern_dict
{% endraw %} {% raw %}

add_hotlines[source]

add_hotlines(datastack_file, ax, vlines=True, clip_vline=True)

Utility function. Adds hotlines and tick labels to plot `ax`.

Instrument peaks are colored black.
{% endraw %} {% raw %}
{% endraw %}